#include "Mesh.h"

CMesh::CMesh(void)
{
	m_pDevice = NULL;
	m_pMesh = NULL;
}


CMesh::~CMesh(void)
{
	Release();
}


CMesh::CMesh(char szName[], IDirect3DDevice9* dev)
{
	m_pDevice = dev;
	m_pMesh = NULL;
	Load(szName, m_pDevice);
}

HRESULT CMesh::Load(char szName[], IDirect3DDevice9* dev)
{
	m_pDevice = dev;

	//	Set white material
	m_White.Ambient = m_White.Specular = m_White.Diffuse = D3DXCOLOR(1.0f, 1.0f, 1.0f, 1.0f);
	m_White.Emissive = D3DXCOLOR(0.0f, 0.0f, 0.0f, 1.0f);
	m_White.Power = 1.0f;

	Release();

	//	Load new mesh
	ID3DXBuffer *pAdjBuffer = NULL;
	ID3DXBuffer *pMatBuffer = NULL;
	DWORD noMaterials = NULL;

	if(FAILED(D3DXLoadMeshFromX(szName, D3DXMESH_MANAGED, m_pDevice,
		&pAdjBuffer, &pMatBuffer, NULL,
		&noMaterials, &m_pMesh)))
		return E_FAIL;

	D3DXMATERIAL *pMats = (D3DXMATERIAL*)pMatBuffer->GetBufferPointer();

	//	Extract and save the materials
	for(unsigned int nMatCount = 0; nMatCount < noMaterials; nMatCount++)
	{
		m_vMaterials.push_back(pMats[nMatCount].MatD3D);

		//	Load texture
		if(pMats[nMatCount].pTextureFilename != NULL)
		{
			char textureFileName[90];
			strcpy_s(textureFileName, "meshes/");
			strcat_s(textureFileName, pMats[nMatCount].pTextureFilename);
			IDirect3DTexture9* pNewTexture = NULL;
			D3DXCreateTextureFromFile(m_pDevice, textureFileName, &pNewTexture);
			m_vTextures.push_back(pNewTexture);
		}
		else
			m_vTextures.push_back(NULL);
	}

	m_pMesh->OptimizeInplace(D3DXMESHOPT_ATTRSORT | D3DXMESHOPT_COMPACT | D3DXMESHOPT_VERTEXCACHE,
		(DWORD*)pAdjBuffer->GetBufferPointer(), NULL, NULL, NULL);

	pAdjBuffer->Release();
	pMatBuffer->Release();

	return S_OK;
}

void CMesh::Render()
{
	for(unsigned int nMatCount = 0; nMatCount < m_vMaterials.size(); nMatCount++)
	{
		if(m_vTextures[nMatCount] != NULL)
			m_pDevice->SetMaterial(&m_White);
		else
			m_pDevice->SetMaterial(&m_vMaterials[nMatCount]);

		m_pDevice->SetTexture(0, m_vTextures[nMatCount]);
		m_pMesh->DrawSubset(nMatCount);
	}
}

void CMesh::Release()
{
	if(m_pMesh != NULL)
	{
		m_pMesh->Release();
		m_pMesh = NULL;
	}

	for(unsigned int nTexCount = 0; nTexCount < m_vTextures.size(); nTexCount++)
		if(m_vTextures[nTexCount] != NULL)
			m_vTextures[nTexCount]->Release();

	m_vTextures.clear();
	m_vMaterials.clear();

}

//////////////////////////////////////////////////////////////////////////
//	MESH INSTANCE
//////////////////////////////////////////////////////////////////////////

CMeshInstance::CMeshInstance()
{
	m_pMesh = NULL;
	m_Pos = m_Rot = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
	m_Scale = D3DXVECTOR3(1.0f, 1.0f, 1.0f);

}

CMeshInstance::CMeshInstance(CMesh *meshPtr)
{
	m_pMesh = meshPtr;
	m_Pos = m_Rot = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
	m_Scale = D3DXVECTOR3(1.0f, 1.0f, 1.0f);
}
D3DXMATRIX CMeshInstance::GetWorldMatrix(void)
{
	D3DXMATRIX p, r, s;
	D3DXMatrixTranslation(&p, m_Pos.x, m_Pos.y, m_Pos.z);
	D3DXMatrixRotationYawPitchRoll(&r, m_Rot.y, m_Rot.x, m_Rot.z);
	D3DXMatrixScaling(&s, m_Scale.x, m_Scale.y, m_Scale.z);


	D3DXMATRIX world = s * r * p;
	return world;
}
void CMeshInstance::Render()
{

	if(m_pMesh != NULL)
	{
		m_pMesh->m_pDevice->SetTransform(D3DTS_WORLD, &GetWorldMatrix());

		m_pMesh->Render();
	}

}


